#include <refbase.h>
#include <mutex>
#include <any>
#include <map>

class Tester : public RefBase {
public:
    static sptr<Tester> GetInstance()
    {
        if (instance == nullptr) {
            static std::mutex mutex;
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new Tester();
            }
        }
        return instance;
    }

    void SetReturnValue(int next, const std::any &val)
    {
        anyMap[next + id] = val;
    }

    bool HasReturnValue()
    {
        return anyMap.find(id++) != anyMap.end();
    }

    std::any GetReturnValue()
    {
        auto ret = anyMap[id - 1];
        anyMap.erase(id - 1);
        return ret;
    }

    template<class T>
    static T Get(const T &b)
    {
        auto tester = Tester::GetInstance();
        if (tester->HasReturnValue()) {
            T ret = false;
            const std::any &retval = tester->GetReturnValue();
            auto pRet = std::any_cast<T>(&retval);
            if (pRet != nullptr) {
                ret = *pRet;
            }
            return ret;
        } else {
            return b;
        }
    }

    template<class T>
    static void Set(int next, const T &b)
    {
        Tester::GetInstance()->SetReturnValue(next, b);
    }

private:
    Tester() = default;
    virtual ~Tester() = default;
    static inline sptr<Tester> instance = nullptr;

    std::map<int, std::any> anyMap;
    int id = 0;
};

bool test()
{
    return Tester::Get<bool>(true);
}

int main()
{
    printf("%d\n", test());

    Tester::Set<bool>(2, false);
    Tester::Set<bool>(4, false);
    printf("0: %d\n", test());
    printf("1: %d\n", test());
    printf("2: %d\n", test());
    printf("3: %d\n", test());
    printf("4: %d\n", test());
    return 0;
}
